package com.zbs.framework.common.utils;

import com.alibaba.fastjson.JSONObject;
import lombok.extern.slf4j.Slf4j;
import okhttp3.*;
import okio.BufferedSink;
import okio.Okio;
import org.springframework.util.CollectionUtils;
import org.springframework.util.ObjectUtils;
import org.springframework.util.StringUtils;

import java.io.File;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.util.HashMap;
import java.util.Map;

/**
 * @description: OkHttp请求
 * @author: Zbs
 * @create: 2020-05-29 12:20
 */
@Slf4j
public class OkHttpUtils {

    public static String buildUrl(Map<String, Object> map) {
        StringBuilder sb = new StringBuilder();
        int i = 1;
        if (map.size() > 0) {
            for (String key : map.keySet()) {
                sb.append(key).append("=");
                if (!StringUtils.hasLength(map.get(key).toString())) {
                    sb.append("&");
                } else {
                    String value = map.get(key).toString();
                    try {
                        value = URLEncoder.encode(value, "UTF-8");
                    } catch (UnsupportedEncodingException e) {
                        e.printStackTrace();
                    }
                    sb.append(value);
                    if (i != map.size()){
                        sb.append("&");
                    }
                    i++;
                }
            }
        }
        return sb.toString();
    }

    /**
     * Get请求
     *
     * @param url URL地址
     * @return 返回结果
     */
    public static String get(String url, Map<String, Object> params) {
        return get(url, params, null);
    }

    /**
     * Get请求
     *
     * @param url URL地址
     * @return 返回结果
     */
    public static String get(String url, Map<String, Object> params, Map<String, String> headers) {
        String result = null;
        try {
            HttpUrl.Builder httpBuilder = HttpUrl.parse(url).newBuilder();
            if (params != null) {
                for (Map.Entry<String, Object> param : params.entrySet()) {
                    httpBuilder.addQueryParameter(param.getKey(), param.getValue().toString());
                }
            }

            OkHttpClient okHttpClient = new OkHttpClient();
            Request.Builder requestBuilder = new Request.Builder().url(httpBuilder.build());
            if (!CollectionUtils.isEmpty(headers)) {
                headers.keySet().forEach(s -> {
                    if (!StringUtils.hasLength(s) && headers.get(s) != null) {
                        requestBuilder.addHeader(s, headers.get(s));
                    }
                });
            }
            Request request = requestBuilder.build();
            Response response = okHttpClient.newCall(request).execute();
            result = response.body().string();
            log.info("Get请求返回：{}", result);
            return result;
        } catch (Exception e) {
            log.error("OkHttp[Get]请求异常", e);
            return result;
        }
    }

    public static String get(String url) { return OkHttpUtils.get(url, null, null); }


    /**
     * Post请求
     *
     * @param url    URL地址
     * @param params 参数
     * @return 返回结果
     */
    public static String post(String url, Map<String, Object> params) {
        return request("post",url, params, null, false);
    }

    /**
     * Post请求
     *
     * @param url    URL地址
     * @param params 参数
     * @return 返回结果
     */
    public static String post(String url, Map<String, Object> params, Map<String, String> headers) {
        return request("post",url, params, headers, false);
    }

    /**
     * Post请求
     *
     * @param url    URL地址
     * @param params 参数
     * @return 返回结果
     */
    public static String postToJson(String url, Map<String, Object> params, Map<String, String> headers) {
        return request("post",url, params, headers, true);
    }

    /**
     * Post请求
     *
     * @param url    URL地址
     * @param params 参数
     * @return 返回结果
     */
    public static String postToJson(String url, Map<String, Object> params) {
        return request("post",url, params, null, true);
    }


    /**
     * put请求
     *
     * @param url    URL地址
     * @param params 参数
     * @return 返回结果
     */
    public static String put(String url, Map<String, Object> params) {
        return request("put",url, params, null, false);
    }

    /**
     * put请求
     *
     * @param url    URL地址
     * @param params 参数
     * @return 返回结果
     */
    public static String put(String url, Map<String, Object> params, Map<String, String> headers) {
        return request("put",url, params, headers, false);
    }

    /**
     * put请求
     *
     * @param url    URL地址
     * @param params 参数
     * @return 返回结果
     */
    public static String putToJson(String url, Map<String, Object> params, Map<String, String> headers) {
        return request("put",url, params, headers, true);
    }

    /**
     * put请求
     *
     * @param url    URL地址
     * @param params 参数
     * @return 返回结果
     */
    public static String putToJson(String url, Map<String, Object> params) {
        return request("put",url, params, null, true);
    }

    /**
     * delete请求
     *
     * @param url    URL地址
     * @param params 参数
     * @return 返回结果
     */
    public static String delete(String url, Map<String, Object> params) {
        return request("delete",url, params, null, false);
    }

    /**
     * delete请求
     *
     * @param url    URL地址
     * @param params 参数
     * @return 返回结果
     */
    public static String delete(String url, Map<String, Object> params, Map<String, String> headers) {
        return request("delete",url, params, headers, false);
    }

    /**
     * delete请求
     *
     * @param url    URL地址
     * @param params 参数
     * @return 返回结果
     */
    public static String deleteToJson(String url, Map<String, Object> params, Map<String, String> headers) {
        return request("delete",url, params, headers, true);
    }

    /**
     * delete请求
     *
     * @param url    URL地址
     * @param params 参数
     * @return 返回结果
     */
    public static String deleteToJson(String url, Map<String, Object> params) {
        return request("delete",url, params, null, true);
    }


    /**
     * request请求
     *
     * @param url    URL地址
     * @param params 参数
     * @return 返回结果
     */
    public static String request(String method, String url, Map<String, Object> params, Map<String, String> headers, boolean isJson) {
        String result = null;
        if (params == null) {
            params = new HashMap<>();
        }
        try {
            OkHttpClient okHttpClient = new OkHttpClient();
            FormBody.Builder formBodyBuilder = new FormBody.Builder();
            //添加参数
            String content = JSONObject.toJSONString(params);
            for (Map.Entry<String, Object> map : params.entrySet()) {
                String key = map.getKey();
                Object value;
                if (map.getValue() == null) {
                    value = "";
                } else {
                    value = map.getValue();
                }
                formBodyBuilder.add(key, value.toString());
            }
            RequestBody requestBody;
            if (isJson) {
                requestBody = FormBody.create(MediaType.parse("application/json"), content);
            } else {
                requestBody = formBodyBuilder.build();
            }
            Request.Builder requestMethod = new Request.Builder().url(url);
            switch (method) {
                case "post":
                    requestMethod.post(requestBody);
                    break;
                case "put":
                    requestMethod.put(requestBody);
                    break;
                case "delete":
                    requestMethod.delete(requestBody);
                    break;
                default:
                    ErrorAssert.error("请求方式错误，允许范围：post put delete");
                    break;
            }
            if (!CollectionUtils.isEmpty(headers)) {
                headers.keySet().forEach(s -> {
                    if (!ObjectUtils.isEmpty(s) && headers.get(s) != null) {
                        requestMethod.addHeader(s, headers.get(s));
                    }
                });
            }
            Request request = requestMethod.build();
            Response response = okHttpClient.newCall(request).execute();
            result = response.body().string();
            log.info("Post请求返回：{}", result);
            return result;
        } catch (Exception e) {
            log.error("OkHttp[Post]请求异常", e);
            return result;
        }
    }


    /**
     * 上传文件请求（Post请求）
     *
     * @param url    URL地址
     * @param params 文件 key：参数名 value：文件 （可以多文件）
     * @return 返回结果
     */
    public static String upload(String url, Map<String, File> params) {
        String result = null;
        try {
            OkHttpClient okHttpClient = new OkHttpClient();
            MultipartBody.Builder multipartBodyBuilder = new MultipartBody.Builder().setType(MultipartBody.FORM);

            for (Map.Entry<String, File> map : params.entrySet()) {
                String key = map.getKey();
                File file = map.getValue();
                if (file == null || (file.exists() && file.length() == 0)) {
                    continue;
                }
                multipartBodyBuilder.addFormDataPart(key, file.getName(), RequestBody.create(MediaType.parse("multipart/form-data"), file));
            }
            RequestBody requestBody = multipartBodyBuilder.build();
            Request request = new Request.Builder().url(url).post(requestBody).build();
            Response response = okHttpClient.newCall(request).execute();
            result = response.body().string();
            log.info("Upload请求返回：{}", result);
            return result;
        } catch (Exception e) {
            log.error("OkHttp[Upload]请求异常", e);
            return result;
        }
    }

    /**
     * 下载文件请求（Get请求）
     *
     * @param url      URL地址
     * @param savePath 保存路径（包括文件名）
     * @return 文件保存路径
     */
    public static String download(String url, String savePath) {
        String result = null;
        try {
            OkHttpClient okHttpClient = new OkHttpClient();
            Request request = new Request.Builder().url(url).build();
            Response response = okHttpClient.newCall(request).execute();
            File file = new File(savePath);
            if (!file.getParentFile().exists()) {
                file.getParentFile().mkdirs();
            }
            BufferedSink sink = Okio.buffer((Okio.sink(file)));
            sink.writeAll(response.body().source());
            sink.flush();
            sink.close();
            result = savePath;
            log.info("Download请求返回：{}", result);
            return result;
        } catch (Exception e) {
            log.error("OkHttp[Download]请求异常", e);
            return result;
        }
    }


}
